package cn.growthgate.fgo.web;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.authz.annotation.RequiresUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;

import cn.growthgate.fgo.entity.MyServant;
import cn.growthgate.fgo.entity.MyServantBond;
import cn.growthgate.fgo.entity.ServantBond;
import cn.growthgate.fgo.service.IMyServantBondService;
import cn.growthgate.fgo.service.IMyServantService;
import cn.growthgate.fgo.service.IServantBondService;
import cn.growthgate.fgo.util.DateUtils;
import cn.growthgate.fgo.web.result.JsonResult;
import cn.growthgate.fgo.web.result.TableResult;

/**
 * <p>
 * 用户表 前端控制器
 * </p>
 *
 * @author GrowthGate
 * @since 2019-01-20
 */
@Controller
@RequestMapping("/myServantBond")
@RequiresUser
public class MyServantBondController {

	@Autowired
	private IMyServantBondService myServantBondService;

	@Autowired
	private IMyServantService myServantService;

	@Autowired
	private IServantBondService servantBondService;

	@RequestMapping("/list")
	public ModelAndView list(Long id) {
		MyServant myServant = myServantService.selectById(id);
		if (myServant == null) {
			throw new AuthorizationException();
		}
		return new ModelAndView("myServantBond/list");
	}

	@ResponseBody
	@RequestMapping("/tableData")
	public TableResult<MyServantBond> tableData(MyServantBond myServantBond, Integer current, Integer size,
			String orderByField, Boolean isAsc) {
		MyServant myServant = myServantService.selectById(myServantBond.getMyServantId());
		if (myServant == null) {
			throw new AuthorizationException();
		}
		Wrapper<MyServantBond> wrapper = new EntityWrapper<>();

		wrapper.eq("myServantId", myServantBond.getMyServantId());
	
		Page<MyServantBond> page = myServantBondService.selectPage(current, size, orderByField, isAsc, wrapper);
		return new TableResult<MyServantBond>(page);
	}

	@RequestMapping("/form")
	public ModelAndView form(Long id, Long myServantId) {
		MyServantBond entity;
		if (id != null) {
			entity = myServantBondService.selectById(id);
			if (entity != null) {
				myServantId = entity.getMyServantId();
			}
		} else {
			entity = new MyServantBond();
			entity.setMyServantId(myServantId);
		}
		MyServant myServant = myServantService.selectById(myServantId);
		if (myServant == null) {
			throw new AuthorizationException();
		}

		return new ModelAndView("myServantBond/form").addObject("entity", entity).addObject("myServant", myServant);
	}

	@ResponseBody
	@RequestMapping("/save")
	public JsonResult save(@Validated MyServantBond myServantBond, BindingResult bindingResult) {
		if (bindingResult.hasErrors()) {
			return JsonResult.fail(bindingResult.getAllErrors().get(0).getDefaultMessage());
		}
		MyServant myServant = myServantService.selectById(myServantBond.getMyServantId());
		if (myServant == null) {
			throw new AuthorizationException();
		}
		// 获取羁绊等级
		int bondLevel = servantBondService.getLevelByValue(myServant.getServantId(), myServantBond.getValue());
		myServantBond.setLevel(bondLevel);
		myServantBondService.insertOrUpdate(myServantBond);
		// 平均每日羁绊
		Integer dailyBond = myServantBondService.getDailyBond(myServant.getId());
		myServant.setDailyBond(dailyBond);
		myServantService.updateById(myServant);
		return JsonResult.ok();
	}

	@ResponseBody
	@RequestMapping("/delete")
	public JsonResult delete(Long[] ids, Long myServantId) {
		MyServant myServant = myServantService.selectById(myServantId);
		if (myServant == null) {
			throw new AuthorizationException();
		}
		if (myServantBondService.deleteBatchIds(Arrays.asList(ids))) {
			// 平均每日羁绊
			Integer dailyBond = myServantBondService.getDailyBond(myServant.getId());
			myServant.setDailyBond(dailyBond);
			myServantService.updateById(myServant);
			return JsonResult.ok("删除成功");
		} else {
			return JsonResult.fail("删除失败");
		}
	}
	
	@ResponseBody
	@RequestMapping("/getChartData")
	public JsonResult getChartData(Long id) {
		MyServant myServant = myServantService.selectById(id);
		if (myServant == null) {
			throw new AuthorizationException();
		}
		Date today = DateUtils.getTodayStart();
		Wrapper<MyServantBond> wrapper = new EntityWrapper<>();
		wrapper.eq("myServantId", id).orderBy("date");
		// 历史羁绊值
		List<MyServantBond> bonds = myServantBondService.selectList(wrapper);
		List<Object[]> data = new ArrayList<>(bonds.size());
		Date tenBondDate = null;
		Date fifteenBondDate = null;
		for (MyServantBond bond : bonds) {
			data.add(new Object[]{bond.getDate(), bond.getValue()});
			if (tenBondDate == null && bond.getLevel() >= 10) {
				// 10绊
				tenBondDate = bond.getDate();
			} else if (fifteenBondDate == null && bond.getLevel() >= 15) {
				// 15绊
				fifteenBondDate = bond.getDate();
			}
		}
		bonds.stream().map(bond -> new Object[]{bond.getDate(), bond.getValue()})
				.collect(Collectors.toList());
		// 从者每级羁绊所需的羁绊值
		List<ServantBond> servantBonds = servantBondService.selectByServantId(myServant.getServantId());
		List<Map<String, Object>> markLineData = new ArrayList<>(servantBonds.size());
		Integer tenBond = 0;
		Integer fifteenBond = 0;
		for (ServantBond servantBond : servantBonds) {
			Map<String, Object> label = new HashMap<>();
			label.put("formatter", "羁绊等级" + servantBond.getLevel());

			Map<String, Object> map = new HashMap<>();
			map.put("yAxis", servantBond.getValue());
			map.put("label", label);
			markLineData.add(map);
			if (servantBond.getLevel() == 10) {
				// 10绊值
				tenBond = servantBond.getValue();
			} else if (servantBond.getLevel() == 15) {
				// 15绊值
				fifteenBond = servantBond.getValue();
			}
		}
		// 拼装统计数据
		Map<String, Object> statistics = new LinkedHashMap<>();
		Date getDate = myServant.getGetDate();
		int getDay = DateUtils.getDiffDay(getDate, today);
		Integer bondValue = myServant.getBondValue();
		statistics.put("获得日期", DateUtils.toString(getDate, DateUtils.DEFAULT_DATE));
		statistics.put("获得天数", getDay);
		if (bondValue != null) {
			statistics.put("当前羁绊等级", myServant.getBondLevel());
			statistics.put("当前羁绊值", bondValue);
			statistics.put("平均每日羁绊（总）", bondValue / getDay);
		} else {
			statistics.put("当前羁绊等级", "未知");
			statistics.put("当前羁绊值", "未填写");
			statistics.put("平均每日羁绊（总）", "无法计算");
		}
		Integer dailyBond = myServant.getDailyBond();
		if (dailyBond != null) {
			statistics.put("平均每日羁绊（当前）", dailyBond);
		} else {
			statistics.put("平均每日羁绊（当前）", "无法计算");
		}
		if (tenBondDate != null) {
			statistics.put("10绊日期", DateUtils.toString(tenBondDate, DateUtils.DEFAULT_DATE));
			statistics.put("10绊天数", DateUtils.getDiffDay(getDate, tenBondDate));
			statistics.put("10绊距离现在天数", DateUtils.getDiffDay(tenBondDate, today));
		} else {
			statistics.put("预计10绊日期", "无法计算");
			statistics.put("预计10绊天数", "无法计算");
			statistics.put("距离预计10绊天数", "无法计算");
		}
		if (fifteenBondDate != null) {
			statistics.put("15绊日期", DateUtils.toString(fifteenBondDate, DateUtils.DEFAULT_DATE));
			statistics.put("15绊天数", DateUtils.getDiffDay(getDate, fifteenBondDate));
			statistics.put("15绊距离现在天数", DateUtils.getDiffDay(fifteenBondDate, today));
		} else {
			statistics.put("预计15绊日期", "无法计算");
			statistics.put("预计15绊天数", "无法计算");
			statistics.put("距离预计15绊天数", "无法计算");
		}
		if (dailyBond != null && dailyBond > 0) {
			int bondSize = bonds.size();
			MyServantBond lastBond = bonds.get(bondSize - 1);
			Integer lastBondValue = lastBond.getValue();
			if (tenBondDate == null && tenBond >= lastBondValue) {
				int diffValue = tenBond - lastBondValue;
				// 如果有小数，不舍全入
				int diffDay = diffValue % dailyBond == 0 ? diffValue / dailyBond : diffValue / dailyBond + 1;
				tenBondDate = DateUtils.addDays(lastBond.getDate(), diffDay);
				statistics.put("预计10绊日期", DateUtils.toString(tenBondDate, DateUtils.DEFAULT_DATE));
				statistics.put("预计10绊天数", DateUtils.getDiffDay(getDate, tenBondDate));
				statistics.put("距离预计10绊天数", DateUtils.getDiffDay(today, tenBondDate));
			}
			if (fifteenBondDate == null && fifteenBond >= lastBondValue) {
				int diffValue = fifteenBond - lastBondValue;
				// 如果有小数，不舍全入
				int diffDay = diffValue % dailyBond == 0 ? diffValue / dailyBond : diffValue / dailyBond + 1;
				fifteenBondDate = DateUtils.addDays(lastBond.getDate(), diffDay);
				statistics.put("预计15绊日期", DateUtils.toString(fifteenBondDate, DateUtils.DEFAULT_DATE));
				statistics.put("预计15绊天数", DateUtils.getDiffDay(getDate, fifteenBondDate));
				statistics.put("距离预计15绊天数", DateUtils.getDiffDay(today, fifteenBondDate));
			}
		}

		return JsonResult.ok("data", data).set("markLineData", markLineData).set("statistics", statistics);
	}

}
